/**
 ******************************************************************************
 * @file           : bsp_timer.c
 * @brief          : Timer Module Implementation (STM32F1xx)
 ******************************************************************************
 * @attention
 *
 * 定时器模块实现
 * 功能：
 *   - 软件定时器（基于SysTick，1ms精度）
 *   - ms/us级延迟函数
 *   - 系统运行时间统计
 *   - 硬件定时器（us级精度，支持4通道）
 *
 * 适配平台：STM32F1xx
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/TIMER/bsp_timer.h"
#include "stm32f1xx_hal.h"

/* ============================================================================ */
/*                          日志配置（用户可修改）                               */
/* ============================================================================ */
/* 日志后端选择：1=EasyLogger, 2=printf, 0=关闭 */
#define TIMER_USE_LOG     0

#if (TIMER_USE_LOG == 1)
    /* 使用EasyLogger */
    #ifndef LOG_TAG
        #define LOG_TAG    "TIMER"
    #endif
    #include "elog.h"
    
#elif (TIMER_USE_LOG == 2)
    /* 使用printf */
    #include <stdio.h>
    #define log_i(fmt, ...)     printf(fmt "\r\n", ##__VA_ARGS__)
    #define log_w(fmt, ...)     printf("[WARN] " fmt "\r\n", ##__VA_ARGS__)
    #define log_e(fmt, ...)     printf("[ERROR] " fmt "\r\n", ##__VA_ARGS__)
    #define log_d(fmt, ...)     printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__)
    
#else
    /* 关闭日志 */
    #define log_i(fmt, ...)
    #define log_w(fmt, ...)
    #define log_e(fmt, ...)
    #define log_d(fmt, ...)
#endif

/* ============================================================================ */
/*                          硬件定时器配置（条件编译）                           */
/* ============================================================================ */

#ifdef HARD_TIM_USE_TIM2
    #define HARD_TIMx                       TIM2
    #define HARD_TIMx_CLK_ENABLE()          __HAL_RCC_TIM2_CLK_ENABLE()
    #define HARD_TIMx_IRQn                  TIM2_IRQn
    #define HARD_TIMx_IRQHandler            TIM2_IRQHandler
#endif

#ifdef HARD_TIM_USE_TIM3
    #define HARD_TIMx                       TIM3
    #define HARD_TIMx_CLK_ENABLE()          __HAL_RCC_TIM3_CLK_ENABLE()
    #define HARD_TIMx_IRQn                  TIM3_IRQn
    #define HARD_TIMx_IRQHandler            TIM3_IRQHandler
#endif

#ifdef HARD_TIM_USE_TIM4
    #define HARD_TIMx                       TIM4
    #define HARD_TIMx_CLK_ENABLE()          __HAL_RCC_TIM4_CLK_ENABLE()
    #define HARD_TIMx_IRQn                  TIM4_IRQn
    #define HARD_TIMx_IRQHandler            TIM4_IRQHandler
#endif

#ifdef HARD_TIM_USE_TIM5
    #define HARD_TIMx                       TIM5
    #define HARD_TIMx_CLK_ENABLE()          __HAL_RCC_TIM5_CLK_ENABLE()
    #define HARD_TIMx_IRQn                  TIM5_IRQn
    #define HARD_TIMx_IRQHandler            TIM5_IRQHandler
#endif

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/* 软件定时器数组 */
static TMR_t s_tmr[TMR_COUNT] = {0};

/* 延迟函数专用变量 */
static volatile uint32_t s_delay_count = 0;
static volatile uint8_t  s_timeout_flag = 0;

/* 系统运行时间（1ms单位，最大24.85天） */
volatile int32_t g_run_time = 0;

/* 硬件定时器回调函数指针 */
static void (*s_hard_timer_callback[4])(void) = {0};

/* SysTick中断使能标志（避免HAL库提前打开中断） */
static volatile uint8_t s_systick_enable = 0;

/* Private function prototypes -----------------------------------------------*/
static void soft_timer_dec(TMR_t *tmr);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       软件定时器递减处理
 *
 * @param[in]   tmr 定时器指针
 *
 * @retval      无
 *
 * @note        每1ms调用一次，由SysTick中断调用
 */
static void soft_timer_dec(TMR_t *tmr)
{
    if (tmr->count > 0)
    {
        if (--tmr->count == 0)
        {
            tmr->flag = 1;  /* 定时到达 */
            
            /* 自动模式：重装计数器 */
            if (tmr->mode == TMR_AUTO_MODE)
            {
                tmr->count = tmr->preload;
            }
        }
    }
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       定时器模块初始化
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        配置SysTick为1ms中断，初始化软件定时器和硬件定时器
 */
void bsp_timer_init(void)
{
    uint8_t i;
    
    log_i("Timer Module Init...");
    
    /* 清零所有软件定时器 */
    for (i = 0; i < TMR_COUNT; i++)
    {
        s_tmr[i].mode = TMR_ONCE_MODE;
        s_tmr[i].flag = 0;
        s_tmr[i].count = 0;
        s_tmr[i].preload = 0;
    }
    
    /* 
     * 配置SysTick为1ms中断
     * SystemCoreClock = 72MHz (STM32F1)
     * SysTick_Config(72000000 / 1000) = 1ms周期
     */
    if (SysTick_Config(SystemCoreClock / 1000) != 0)
    {
        log_e("SysTick_Config failed");
        return;
    }
    
    /* 使能SysTick中断处理 */
    s_systick_enable = 1;
    
    /* 初始化硬件定时器 */
    bsp_hard_timer_init();
    
    log_i("Timer Module Init OK (SysTick=1ms, Soft Timer=%d)", TMR_COUNT);
}

/**
 * @brief       ms级延迟函数
 *
 * @param[in]   ms 延迟时间（ms）
 *
 * @retval      无
 *
 * @note        基于SysTick实现，精度±1ms
 * @note        延迟期间可响应中断
 */
void bsp_delay_ms(uint32_t ms)
{
    if (ms == 0)
    {
        return;
    }
    else if (ms == 1)
    {
        ms = 2;  /* 确保至少2ms */
    }
    
    __disable_irq();
    s_delay_count = ms;
    s_timeout_flag = 0;
    __enable_irq();
    
    while (s_timeout_flag == 0)
    {
        /* 调用空闲函数（喂狗、省电等） */
        extern void bsp_Idle(void);
        bsp_Idle();
        
        __NOP();
    }
}

/**
 * @brief       us级延迟函数
 *
 * @param[in]   us 延迟时间（us）
 *
 * @retval      无
 *
 * @note        基于SysTick计数器实现
 * @note        延迟期间不响应中断，适合精确短延迟
 */
void bsp_delay_us(uint32_t us)
{
    uint32_t ticks;
    uint32_t told;
    uint32_t tnow;
    uint32_t tcnt = 0;
    uint32_t reload;
    
    reload = SysTick->LOAD;
    ticks = us * (SystemCoreClock / 1000000);  /* 需要的节拍数 */
    
    told = SysTick->VAL;
    
    while (1)
    {
        tnow = SysTick->VAL;
        
        if (tnow != told)
        {
            /* SysTick是递减计数器 */
            if (tnow < told)
            {
                tcnt += told - tnow;
            }
            else  /* 发生重载 */
            {
                tcnt += reload - tnow + told;
            }
            
            told = tnow;
            
            /* 时间到 */
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }
}

/**
 * @brief       启动单次定时器
 *
 * @param[in]   id 定时器ID（0 ~ TMR_COUNT-1）
 * @param[in]   period 定时周期（ms）
 *
 * @retval      无
 *
 * @note        定时到后自动停止
 */
void bsp_start_timer(uint8_t id, uint32_t period)
{
    if (id >= TMR_COUNT)
    {
        log_e("Invalid timer ID: %d (max=%d)", id, TMR_COUNT-1);
        return;
    }
    
    if (period == 0)
    {
        log_w("Timer[%d] period=0, set to 1ms", id);
        period = 1;
    }
    
    log_d("Start Timer[%d]: %d ms (ONCE)", id, period);
    
    __disable_irq();
    
    s_tmr[id].mode = TMR_ONCE_MODE;
    s_tmr[id].flag = 0;
    s_tmr[id].count = period;
    s_tmr[id].preload = period;
    
    __enable_irq();
}

/**
 * @brief       启动自动定时器
 *
 * @param[in]   id 定时器ID（0 ~ TMR_COUNT-1）
 * @param[in]   period 定时周期（ms）
 *
 * @retval      无
 *
 * @note        定时到后自动重装，周期触发
 */
void bsp_start_auto_timer(uint8_t id, uint32_t period)
{
    if (id >= TMR_COUNT)
    {
        log_e("Invalid timer ID: %d (max=%d)", id, TMR_COUNT-1);
        return;
    }
    
    if (period == 0)
    {
        log_w("Timer[%d] period=0, set to 1ms", id);
        period = 1;
    }
    
    log_d("Start Timer[%d]: %d ms (AUTO)", id, period);
    
    __disable_irq();
    
    s_tmr[id].mode = TMR_AUTO_MODE;
    s_tmr[id].flag = 0;
    s_tmr[id].count = period;
    s_tmr[id].preload = period;
    
    __enable_irq();
}

/**
 * @brief       停止定时器
 *
 * @param[in]   id 定时器ID（0 ~ TMR_COUNT-1）
 *
 * @retval      无
 */
void bsp_stop_timer(uint8_t id)
{
    if (id >= TMR_COUNT)
    {
        log_e("Invalid timer ID: %d (max=%d)", id, TMR_COUNT-1);
        return;
    }
    
    log_d("Stop Timer[%d]", id);
    
    __disable_irq();
    
    s_tmr[id].count = 0;
    s_tmr[id].flag = 0;
    s_tmr[id].mode = TMR_ONCE_MODE;
    
    __enable_irq();
}

/**
 * @brief       检查定时器是否到期
 *
 * @param[in]   id 定时器ID（0 ~ TMR_COUNT-1）
 *
 * @retval      0=未到期，1=已到期
 *
 * @note        检查后会自动清除到期标志
 */
uint8_t bsp_check_timer(uint8_t id)
{
    if (id >= TMR_COUNT)
    {
        return 0;
    }
    
    if (s_tmr[id].flag == 1)
    {
        s_tmr[id].flag = 0;
        return 1;
    }
    
    return 0;
}

/**
 * @brief       获取系统运行时间
 *
 * @param       无
 *
 * @retval      运行时间（ms）
 *
 * @note        最长表示24.85天，超过会溢出
 */
int32_t bsp_get_run_time(void)
{
    int32_t runtime;
    
    __disable_irq();
    runtime = g_run_time;
    __enable_irq();
    
    return runtime;
}

/**
 * @brief       计算时间差
 *
 * @param[in]   last_time 上次时间戳
 *
 * @retval      时间差（ms）
 *
 * @note        自动处理溢出情况
 */
int32_t bsp_check_run_time(int32_t last_time)
{
    int32_t now_time;
    int32_t diff;
    
    __disable_irq();
    now_time = g_run_time;
    __enable_irq();
    
    if (now_time >= last_time)
    {
        diff = now_time - last_time;
    }
    else
    {
        /* 处理溢出：0x7FFFFFFF - last_time + now_time */
        diff = 0x7FFFFFFF - last_time + now_time;
    }
    
    return diff;
}

/**
 * @brief       SysTick中断服务函数
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        每1ms进入一次
 */
void SysTick_Handler(void)
{
    uint8_t i;
    
    /* HAL库的SysTick处理 */
    HAL_IncTick();
    
    /* 等待初始化完成 */
    if (s_systick_enable == 0)
    {
        return;
    }
    
    /* 延迟函数计时 */
    if (s_delay_count > 0)
    {
        if (--s_delay_count == 0)
        {
            s_timeout_flag = 1;
        }
    }
    
    /* 软件定时器递减 */
    for (i = 0; i < TMR_COUNT; i++)
    {
        soft_timer_dec(&s_tmr[i]);
    }
    
    /* 系统运行时间累加 */
    g_run_time++;
    if (g_run_time == 0x7FFFFFFF)
    {
        g_run_time = 0;
    }
}

/* ============================================================================ */
/*                          硬件定时器实现                                       */
/* ============================================================================ */

#ifdef HARD_TIMx

/**
 * @brief       硬件定时器初始化
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        配置为us级自由运行定时器
 * @note        STM32F1: APB1时钟=36MHz，TIMxCLK=72MHz
 */
void bsp_hard_timer_init(void)
{
    TIM_HandleTypeDef tim_handle = {0};
    uint32_t prescaler;
    uint32_t period;
    
    /* 使能定时器时钟 */
    HARD_TIMx_CLK_ENABLE();
    
    /*
     * STM32F1时钟配置：
     * HCLK = SYSCLK = 72MHz
     * PCLK1 = HCLK / 2 = 36MHz
     * TIM2-5时钟 = PCLK1 x 2 = 72MHz（APB1预分频不为1时）
     */
    
    /* 预分频：72MHz / 72 = 1MHz，即1us计数一次 */
    prescaler = (SystemCoreClock / 2) / 1000000 - 1;
    
    /* 自动重装值：TIM2/5是32位，TIM3/4是16位 */
    #if (defined(HARD_TIM_USE_TIM2) || defined(HARD_TIM_USE_TIM5))
        period = 0xFFFFFFFF;  /* 32位定时器 */
    #else
        period = 0xFFFF;      /* 16位定时器 */
    #endif
    
    /* 配置定时器 */
    tim_handle.Instance = HARD_TIMx;
    tim_handle.Init.Prescaler = prescaler;
    tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    tim_handle.Init.Period = period;
    tim_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    tim_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    
    HAL_TIM_Base_Init(&tim_handle);
    
    /* 配置中断 */
    HAL_NVIC_SetPriority(HARD_TIMx_IRQn, 0, 2);
    HAL_NVIC_EnableIRQ(HARD_TIMx_IRQn);
    
    /* 启动定时器 */
    HAL_TIM_Base_Start(&tim_handle);
}

/**
 * @brief       启动硬件定时器通道
 *
 * @param[in]   channel 通道号（1~4）
 * @param[in]   timeout_us 超时时间（us）
 * @param[in]   callback 超时回调函数
 *
 * @retval      无
 *
 * @note        定时精度±1us
 */
void bsp_start_hard_timer(uint8_t channel, uint32_t timeout_us, void (*callback)(void))
{
    uint32_t cnt_now;
    uint32_t cnt_target;
    
    if (channel < 1 || channel > 4 || callback == NULL)
    {
        return;
    }
    
    cnt_now = HARD_TIMx->CNT;
    cnt_target = cnt_now + timeout_us;
    
    /* 保存回调函数 */
    s_hard_timer_callback[channel - 1] = callback;
    
    /* 配置捕获比较寄存器和中断 */
    switch (channel)
    {
        case 1:
            HARD_TIMx->CCR1 = cnt_target;
            HARD_TIMx->SR = (uint16_t)~TIM_IT_CC1;
            HARD_TIMx->DIER |= TIM_IT_CC1;
            break;
            
        case 2:
            HARD_TIMx->CCR2 = cnt_target;
            HARD_TIMx->SR = (uint16_t)~TIM_IT_CC2;
            HARD_TIMx->DIER |= TIM_IT_CC2;
            break;
            
        case 3:
            HARD_TIMx->CCR3 = cnt_target;
            HARD_TIMx->SR = (uint16_t)~TIM_IT_CC3;
            HARD_TIMx->DIER |= TIM_IT_CC3;
            break;
            
        case 4:
            HARD_TIMx->CCR4 = cnt_target;
            HARD_TIMx->SR = (uint16_t)~TIM_IT_CC4;
            HARD_TIMx->DIER |= TIM_IT_CC4;
            break;
    }
}

/**
 * @brief       硬件定时器中断处理函数
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        在stm32f1xx_it.c中调用
 */
void HARD_TIMx_IRQHandler(void)
{
    uint16_t status;
    uint16_t enable;
    
    /* 通道1 */
    status = HARD_TIMx->SR & TIM_IT_CC1;
    enable = HARD_TIMx->DIER & TIM_IT_CC1;
    if (status && enable)
    {
        HARD_TIMx->SR = (uint16_t)~TIM_IT_CC1;
        HARD_TIMx->DIER &= (uint16_t)~TIM_IT_CC1;
        
        if (s_hard_timer_callback[0] != NULL)
        {
            s_hard_timer_callback[0]();
        }
    }
    
    /* 通道2 */
    status = HARD_TIMx->SR & TIM_IT_CC2;
    enable = HARD_TIMx->DIER & TIM_IT_CC2;
    if (status && enable)
    {
        HARD_TIMx->SR = (uint16_t)~TIM_IT_CC2;
        HARD_TIMx->DIER &= (uint16_t)~TIM_IT_CC2;
        
        if (s_hard_timer_callback[1] != NULL)
        {
            s_hard_timer_callback[1]();
        }
    }
    
    /* 通道3 */
    status = HARD_TIMx->SR & TIM_IT_CC3;
    enable = HARD_TIMx->DIER & TIM_IT_CC3;
    if (status && enable)
    {
        HARD_TIMx->SR = (uint16_t)~TIM_IT_CC3;
        HARD_TIMx->DIER &= (uint16_t)~TIM_IT_CC3;
        
        if (s_hard_timer_callback[2] != NULL)
        {
            s_hard_timer_callback[2]();
        }
    }
    
    /* 通道4 */
    status = HARD_TIMx->SR & TIM_IT_CC4;
    enable = HARD_TIMx->DIER & TIM_IT_CC4;
    if (status && enable)
    {
        HARD_TIMx->SR = (uint16_t)~TIM_IT_CC4;
        HARD_TIMx->DIER &= (uint16_t)~TIM_IT_CC4;
        
        if (s_hard_timer_callback[3] != NULL)
        {
            s_hard_timer_callback[3]();
        }
    }
}

#else
    /* 未定义硬件定时器时的空实现 */
    void bsp_hard_timer_init(void) {}
    void bsp_start_hard_timer(uint8_t channel, uint32_t timeout_us, void (*callback)(void)) {}
#endif
